package paim.gh.model.modelos;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.hibernate.Session;

import com.google.common.collect.Lists;
import com.google.common.primitives.Chars;

import paim.wingchun.app.Reflections;
import paim.wingchun.model.modelos.Model;
import paim.wingchun.model.modelos.ErroModel.Level;
import paim.wingchun.model.modelos.ErroModel.Tipo;
import paim.wingchun.model.pojos.Erro;
import paim.wingchun.model.pojos.Pojo;

import paim.gh.model.Legendas;
import paim.gh.model.pojos.Aula;
import paim.gh.model.pojos.Periodo;
import paim.gh.model.pojos.Preferencia;
import paim.gh.model.pojos.Professor;
import paim.gh.model.pojos.Turma;

public class TurmaModel extends Model<Turma> {

    private final static char UNICA = 'u';

    private static final char[] LEGENDAS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

    private static TurmaModel modelo;

    private TurmaModel() {}

    public static TurmaModel getInstance() {
        if ( modelo == null )
            modelo = new TurmaModel();

        return modelo;
    }

    public Turma addTurma(Session session, Aula aula) throws Exception {
        if ( aula.getTurmas().size() >= LEGENDAS.length )
            throw new Exception("overflow numero de turmas");

        /* se ja tem uma preciso reajustar */
        if ( aula.isTurmaUnica() && aula.getTurmas().get(0).getLegenda().equals(UNICA) ) {
            aula.primeiraTurma().setLegenda(nextLegenda(aula));
        }

        Turma turmanova = new Turma();
        turmanova.setLegenda(nextLegenda(aula));
        turmanova.setAula(aula);
        aula.getTurmas().add(turmanova);

        AulaModel.getInstance().saveOrUpdate(session, aula);

        return turmanova;
    }

    public boolean removeTurma(Session session, Aula aula, Turma turma) throws Exception {
        if ( aula.getTurmas().size() <= 1 )
            throw new Exception("underflow numero de turmas");

        aula.getTurmas().remove(turma);

        if ( aula.isTurmaUnica() )
            aula.primeiraTurma().setLegenda(UNICA);

        AulaModel.getInstance().saveOrUpdate(session, aula);

        return true;
    }

    private Character nextLegenda(Aula aula) throws Exception {
        if ( aula.getTurmas().isEmpty() )
            return UNICA;

        List<Character> usadas = Lists.transform(aula.getTurmas(), new Legendas());
        List<Character> todas = Chars.asList(LEGENDAS);
        Collection<Character> livres = CollectionUtils.subtract(todas, usadas);

        if ( livres.isEmpty() )
            throw new Exception("maximo de posicoes ocupadas");

        /* deve verificar e essa faz parte da lista, senao pega primeira disponivel */
        return (new ArrayList<Character>(livres)).get(0);
    }

    public void realocarLegenda(Aula aula) {

    }

    // FIXME cuidado aqui , tem que levar em conta que preferencia tem Turma e nao periodo
    @Override
    public List<Erro> couplings(Session session, Pojo pojo) throws Exception {
        List<Erro> engates = new ArrayList<>();
        String fieldName = Reflections.getFieldName(Professor.class);

        /* primeiro procura em preferencias */
        List<Preferencia> listP = PreferenciaModel.getInstance().getObjetos(session, pojo);

        for ( Preferencia p : listP ) {
            Erro engate = new Erro(3L, Level.ERRO$IMPEDITIVO, Tipo.EXCLUSAO, p, fieldName, new String[] {
                            pojo.toString(),
                            p.toString() });
            engates.add(engate);
        }

        List<Periodo> listAS = PeriodoModel.getInstance().getObjetos(session, pojo);
        for ( Periodo as : listAS ) {

            Erro engate = new Erro(3L, Level.ERRO$IMPEDITIVO, Tipo.EXCLUSAO, as, fieldName, new String[] {
                            pojo.toString(),
                            as.toString() });
            engates.add(engate);
        }

        return engates;
    }

}
